package com.robusta.cityuate.activities;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.robusta.cityuate.R;
import com.robusta.cityuate.base.CityuateItemizedOverlay;
import com.robusta.cityuate.base.CityuateMapActivity;
import com.robusta.cityuate.objects.Spot;
import com.robusta.cityuate.services.CityuateBroadCastReceiver;
import com.robusta.cityuate.services.HTTPService;
import com.robusta.cityuate.services.SpotCreateEditService;
import com.robusta.cityuate.utils.ConnectionUtils;
import com.robusta.cityuate.utils.Images;

//this class is responsible for creating a new reminder
public class SpotCreateEditActivity extends CityuateMapActivity {
	// all the needed attributes

	private LocationManager locationManager;
	private MapView mapView;
	private MapController mapController;
	private MyLocationOverlay myLocationOverlay;
	private List<Overlay> mapOverLay;
	private EditText longitude;
	private EditText latitude;
	private Button createEdit;
	private CityuateItemizedOverlay spotsOverlayedMarkers;
	private Drawable spotMarker;
	protected OverlayItem item;
	private EditText comment;
	private EditText name;
	private EditText address;

	private ImageView preview;
	private LocationProvider locationProvider;

	private Context mContext = this;
	private ImageButton resetMapLocation;
	private Bitmap photo;

	private ImageLoader mImageDownloader;

	private static final int TAKE_PICTURE = 0;
	private static final int SELECT_PICTURE = 1;
	private static final String TAG = SpotCreateEditActivity.class.getName();
	public static final String IS_EDIT = "isEdit";
	public static final int SPOT_CREATEEDIT_CODE = 1;

	private CityuateBroadCastReceiver receiver = new CityuateBroadCastReceiver() {

		@Override
		public void onSuccess() {
			spotCreateSuccess();
		}

		@Override
		public void onFailure() {
			spotCreateFail();

		}

		@Override
		public void onCancel() {
			enableView();
			setSupportProgressBarIndeterminateVisibility(false);
			ConnectionUtils.clearConnection(mContext, TAG);
		}

	};
	private boolean isEdit;
	private Spot spot;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.spot_create_edit);

		Bundle extras = getIntent().getExtras();
		if (extras != null)
			isEdit = extras.getBoolean(IS_EDIT, false);

		mapView = (MapView) findViewById(R.id.create_edit_mapView);
		name = (EditText) findViewById(R.id.create_edit_spot_name);
		address = (EditText) findViewById(R.id.create_edit_spot_address);
		longitude = (EditText) findViewById(R.id.create_edit_spot_long);
		latitude = (EditText) findViewById(R.id.create_edit_spot_lat);
		comment = (EditText) findViewById(R.id.create_edit_spot_comment);
		createEdit = (Button) findViewById(R.id.create_edit_spot_create);
		preview = (ImageView) findViewById(R.id.create_edit_spot_preview);
		registerForContextMenu(preview);
		resetMapLocation = (ImageButton) findViewById(R.id.reset);
		resetMapLocation.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				setLocationOnMap();
			}
		});
		if (isEdit)
			createEdit.setText(R.string.edit);
		createEdit.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				// check if fields are not empty
				if (checkFieldsNotEmpty())
					// fire connection to create spot service
					fireCreateEditRequestToServer();

			}
		});

		// mapView.setStreetView(true);
		mapController = mapView.getController();
		mapController.setZoom(14);

		myLocationOverlay = new MyLocationOverlay(this, mapView) {
			// add a bubble on the screen and get is coordinate from the map
			@Override
			public boolean onTap(GeoPoint p, MapView map) {
				if (!isEdit) {
					longitude.setText((double) (p.getLongitudeE6() / 1000000.0)
							+ "");
					latitude.setText((double) (p.getLatitudeE6() / 1000000.0)
							+ "");
					spotsOverlayedMarkers.removeAll();
					spotsOverlayedMarkers.hideAllBalloons();
					item = new OverlayItem(p, "YourSpot", comment.getText()
							.toString());
					spotsOverlayedMarkers.addOverlay(item);
				}
				return super.onTap(p, map);
			}
		};

		// map adjustment + running the gps
		mapView.displayZoomControls(false);
		mapOverLay = mapView.getOverlays();
		mapOverLay.add(myLocationOverlay);
		myLocationOverlay.enableCompass();
		myLocationOverlay.enableMyLocation();
		myLocationOverlay.getLastFix();
		spotMarker = getResources().getDrawable(R.drawable.marker);
		spotsOverlayedMarkers = new CityuateItemizedOverlay(spotMarker, mapView);
		mapOverLay.add(spotsOverlayedMarkers);
		initLocationListener();

		if (isEdit) {
			// fill fields
			spot = (Spot) extras.getSerializable(Spot.SPOT);
			name.setText(spot.getName());
			address.setText(spot.getAddress());
			latitude.setText("" + spot.getLat());
			latitude.setEnabled(false);
			longitude.setText("" + spot.getLongt());
			longitude.setEnabled(false);
			comment.setText(spot.getLandmarks());
			Log.e("coo", spot.getLat() + "," + spot.getLongt());
			GeoPoint spotLocation = new GeoPoint(
					((int) (spot.getLat() * 1000000)),
					((int) (spot.getLongt() * 1000000)));
			mapController.animateTo(spotLocation);
			item = new OverlayItem(spotLocation, getString(R.string.your_spot),
					comment.getText().toString());
			spotsOverlayedMarkers.addOverlay(item);
			mImageDownloader = ImageLoader.getInstance();
			mImageDownloader.displayImage(spot.getImgURL(), preview);
		}
	}

	@Override
	protected void onResume() {
		Log.d(TAG, "onResume");
		// initiate the receiver
		IntentFilter filter = new IntentFilter();
		filter.addAction(TAG);
		registerReceiver(receiver, filter);
		// No current connection
		if (!ConnectionUtils.isConnecting(mContext, TAG))
		// it was connected
		{
			if (ConnectionUtils.wasConnected(mContext, TAG))
				// connection was successful
				if (ConnectionUtils.isResultSuccessful(mContext, TAG))
					spotCreateSuccess();
				else
					// it failed
					spotCreateFail();
		} else { // there is an active connection
			disableView();
			setSupportProgressBarIndeterminateVisibility(true);
		}
		super.onResume();
	}

	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case SELECT_PICTURE: {
				Uri selectedImageUri = data.getData();
				// selectedImagePath = getPath(selectedImageUri);
				InputStream is;
				try {
					is = getContentResolver().openInputStream(selectedImageUri);
					photo = BitmapFactory.decodeStream(is);
					is.close();

				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				preview.setImageBitmap(photo);
				break;
			}
			case TAKE_PICTURE: {
				if (data != null) {
					photo = (Bitmap) data.getExtras().get("data");
					preview.setImageBitmap(photo);
				}
				break;
			}

			}
		}
	}

	private class GeoUpdateHandler implements LocationListener {

		@Override
		public void onLocationChanged(Location location) {
		}

		@Override
		public void onProviderDisabled(String provider) {
		}

		@Override
		public void onProviderEnabled(String provider) {
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {

		}
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	/**
	 * add data to bundle and fire CreateSpot Service
	 */
	private void fireCreateEditRequestToServer() {
		// Check if no connection pop up a dialog
		if (!ConnectionUtils.isNetworkAvailable(mContext)) {
			// No connection
			ConnectionUtils.showNoConnectionDialog(mContext);
			return;
		} else { // Connection is available
			// Start loading dialog and connecting variables
			disableView();
			setSupportProgressBarIndeterminateVisibility(true);

			// start back-ground service to handle Create process
			Intent backgroud_regService = new Intent(this,
					SpotCreateEditService.class);
			backgroud_regService.setAction(TAG);

			backgroud_regService.putExtra(HTTPService.LOGIN_RQUIRED, true);
			backgroud_regService.putExtra(IS_EDIT, isEdit);

			if (isEdit)// add id only if it's edit
				backgroud_regService.putExtra(Spot.SPOT_ID, spot.getId());
			backgroud_regService.putExtra(Spot.SPOT_NAME, name.getText()
					.toString());
			backgroud_regService.putExtra(Spot.SPOT_DESCRIPTION, address
					.getText().toString());
			backgroud_regService.putExtra(Spot.SPOT_LONG, longitude.getText()
					.toString());
			backgroud_regService.putExtra(Spot.SPOT_LAT, latitude.getText()
					.toString());
			backgroud_regService.putExtra(Spot.SPOT_LANDMARKS, (comment
					.getText() == null) ? "" : comment.getText().toString());

			// image

			if ( photo != null) {
				String photoBase64 = Images.encodeTobase64(photo);
				backgroud_regService.putExtra(Spot.SPOT_FILE, photoBase64);
				// send image name
				backgroud_regService
						.putExtra(Spot.SPOT_FILENAME, "spotLog.jpg");
			}

			startService(backgroud_regService);
			Log.e(TAG, "Fired CreateSpot service");

		}

	}

	private void initLocationListener() {
		// Criteria for choosing location provider
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setPowerRequirement(Criteria.POWER_LOW);

		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		locationProvider = locationManager.getProvider(locationManager
				.getBestProvider(criteria, true));
		Log.e(TAG, "Provider " + locationProvider.getName());

		// Notify user if there is no way to track the device
		if (locationManager.isProviderEnabled(locationProvider.getName())) {
			return;
		} else {

			locationManager.requestLocationUpdates(locationProvider.getName(),
					0, 0, new GeoUpdateHandler());
		}
	}

	private void setLocationOnMap() {

		if (myLocationOverlay.getMyLocation() != null)
			mapController.animateTo(myLocationOverlay.getMyLocation());
		else
			Toast.makeText(mContext, R.string.location_unavailable,
					Toast.LENGTH_SHORT).show();
	}

	/**
	 * checks if any of the fields is empty
	 */
	private boolean checkFieldsNotEmpty() {
		if ((longitude.getText().length() == 0)
				|| (latitude.getText().length() == 0)
				|| (name.getText().length() == 0)
				|| (address.getText().length() == 0))

		{
			Toast.makeText(mContext, getString(R.string.long_lat_warning),
					Toast.LENGTH_LONG).show();
			return false;
		}
		if (!isEdit && photo == null) {
//			Toast.makeText(mContext, getString(R.string.photo_warning),
//					Toast.LENGTH_LONG).show();
//			return false;
			photo=((BitmapDrawable)getResources().getDrawable(R.drawable.no_image)).getBitmap();
		}
		return true;

	}

	/**
	 * success scenario
	 */
	private void spotCreateSuccess() {
		setSupportProgressBarIndeterminateVisibility(false);
		Log.d(TAG, "SpotCreatedSuccess method");
		enableView();
		setResult(RESULT_OK);
		if (!isEdit)
			Toast.makeText(mContext, getString(R.string.spot_created),
					Toast.LENGTH_LONG).show();
		else
			Toast.makeText(mContext, getString(R.string.spot_edited),
					Toast.LENGTH_LONG).show();
		finish();

	}

	/**
	 * failure scenario
	 */
	private void spotCreateFail() {
		setSupportProgressBarIndeterminateVisibility(false);
		Log.d(TAG, "Spot Fail method");

		enableView();
		// show failure message
		Toast.makeText(mContext, ConnectionUtils.getExtra(mContext, TAG),
				Toast.LENGTH_LONG).show();
		ConnectionUtils.clearConnection(mContext, TAG);

	}

	@Override
	protected void onPause() {
		Log.e("onPause", "OnPause");
		unregisterReceiver(receiver);
		if (!ConnectionUtils.isConnecting(mContext, TAG)) {
			ConnectionUtils.clearConnection(mContext, TAG);
		}
		super.onPause();
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		Intent intent;
		switch (item.getItemId()) {
		case R.id.camera:
			intent = new Intent("android.media.action.IMAGE_CAPTURE");
			startActivityForResult(intent, TAKE_PICTURE);
			return true;
		case R.id.gallary:
			intent = new Intent();
			intent.setType("image/*");
			intent.setAction(Intent.ACTION_GET_CONTENT);
			startActivityForResult(Intent.createChooser(intent, getResources()
					.getString(R.string.spot_select_photo)), SELECT_PICTURE);
			return true;
		}
		return super.onContextItemSelected(item);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		menu.setHeaderTitle(getString(R.string.add_photo));
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.spot_create_context_menu, menu);
	}

	private void disableView() {
		name.setEnabled(false);
		address.setEnabled(false);
		latitude.setEnabled(false);
		longitude.setEnabled(false);
		comment.setEnabled(false);
		createEdit.setEnabled(false);
		preview.setEnabled(false);

	}

	private void enableView() {
		name.setEnabled(true);
		address.setEnabled(true);
		if (!isEdit) {
			latitude.setEnabled(true);
			longitude.setEnabled(true);
		}
		comment.setEnabled(true);
		createEdit.setEnabled(true);
		preview.setEnabled(true);

	}
	
	@Override
	public void onBackPressed() {
		if (ConnectionUtils.isConnecting(mContext, TAG)) {
			enableView();
			setSupportProgressBarIndeterminateVisibility(false);
			Intent loginCancel = new Intent(TAG + HTTPService.CANCEL);
			sendBroadcast(loginCancel);
			ConnectionUtils.clearConnection(mContext, TAG);
		} else
			super.onBackPressed();
	}

}